﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using UnityEditor;
using UnityEngine;

namespace Cemit.NetFramework
{
    /// <summary>
    /// 让静态程序拥有对Unity主线程的访问, MonoHandlerk将自动设置为不销毁的物体
    /// </summary>
    public class MonoHandler : MonoBehaviour, IMonoHandler
    {
        public event Action OnUpdate;
        public event Action OnLateUpdate;
        public event Action OnFixedUpdate;

        Action m_UpdateAction;
        Action m_TempUpdateAction;
        Action m_NextUpdateAction;

        private bool m_IsUpdating = false;

        public static MonoHandler Create(string gameObjectName)
        {
            return new GameObject(gameObjectName)
                .AddComponent<MonoHandler>();
        }

        private void Awake()
        {
            Debug.Log($"已创建MonoHandler: {gameObject.name}");
            DontDestroyOnLoad(gameObject);
        }

        private void FixedUpdate()
        {
            OnFixedUpdate?.Invoke();
        }

        private void LateUpdate()
        {
            OnLateUpdate?.Invoke();
        }

        void Update()
        {
            m_IsUpdating = true;

            m_UpdateAction?.Invoke();

            //添加上当前UpdateAction添加的委托
            m_UpdateAction = m_TempUpdateAction;
            m_TempUpdateAction = null;

            //添加上一帧的委托
            m_UpdateAction += m_NextUpdateAction;
            m_NextUpdateAction = null;

            OnUpdate?.Invoke();

            m_IsUpdating = false;
        }

        /// <summary>
        /// 在Unity主线程的下一帧调用一个方法（仅在下一次Update执行一次）
        /// </summary>
        public void InvokeAtNextFrame(Action action)
        {
            m_NextUpdateAction += action;
        }

        /// <summary>
        /// 在Unity主线程中调用一个方法（仅在Update执行一次）
        /// </summary>
        public void Invoke(Action action)
        {
            // 如果正在Update，则加入缓存，等到下次Update执行
            if (m_IsUpdating)
            {
                m_TempUpdateAction += action;
            }
            else
            {
                m_UpdateAction += action;
            }
        }
    }
}
